package com.shockweb.service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;

import com.shockweb.bridge.HostInfo;
import com.shockweb.bridge.ServerInfo;
import com.shockweb.service.data.ServiceStatus;
import com.shockweb.client.impl.RegisterClient;
import com.shockweb.common.log.LogManager;
import com.shockweb.service.config.ServiceConfig;

/**
 * 与注册服务器同步数据的服务
 * 
 * @author 彭明华
 * 2018年1月3日 创建
 */
public class SyncThread implements Runnable{

	
	/**
	 * 当前同步服务实例
	 */
	private static SyncThread instance = null;
	
	/**
	 * 启动的同步线程
	 */
	private Thread thread = null;

	
	/**
	 * 获取当前实例
	 * @return
	 */
	public static SyncThread getInstance(){
		return instance;
	}
	

	/**
	 * 注册服务器的配置
	 */
	private ServiceConfig config = null;
	
	/**
	 * 启动服务
	 * @param servers
	 */
	public synchronized static void start(ServiceConfig config)throws ServiceServerException {
		if(instance == null){
			instance = new SyncThread();
		}
		instance.config = config;
		if(config.getRegisterServerUrls()!=null){
			ServerManager.init(config);
		}else{
			throw new ServiceServerException("注册服务器地址不能为空");
		}
		instance.thread = new Thread(instance);
		instance.thread.start();
	}

	/**
	 * 是否停止
	 */
	private boolean stop = false;
	

	/**
	 * 公共延迟方法
	 */
    private static void timeDelay(int time) {
		try {
			long t = time - System.currentTimeMillis() % time;
			if (t > 0) {
				Thread.sleep(t);
			}
		} catch (InterruptedException e) {
		}
	}
    
    /**
     * 前一次的调用次数
     */
    private long prevCalled = 0; 
    
    /**
     * 前一次的超时次数
     */
    private long prevTimeOut = 0; 
    
	/**
	 * 同步异步方法
	 */
	public void run() {
		stop = false;
		long index = 0;
		while(!stop){
			ServerInfo serverInfo = new ServerInfo();
			serverInfo.setSpaceName(ServiceStatus.getServices().getSpaceName());
			List<String> serviceNames = new ArrayList<String>();
			Iterator<Entry<String,Long>> its = ServiceStatus.getServices().getServiceDefines().entrySet().iterator();
			while(its.hasNext()){
				Entry<String,Long> entry = its.next();
				serviceNames.add(entry.getKey());
			}
			serverInfo.setServiceNames(serviceNames);
			serverInfo.setHost(ServiceServer.getServer().getConfig().getHostUrl());
			long tmp = ServiceServerNettyHandler.getCalled();
			long called = tmp - prevCalled;
			prevCalled = tmp;
			serverInfo.setCalled(called);
			
			tmp = ServiceServerNettyHandler.getError();
			long timeOut = tmp - prevTimeOut;
			prevTimeOut = tmp;
			serverInfo.setTimeOut(timeOut);
			serverInfo.setDoing(ServiceServerNettyHandler.getDoing());
			serverInfo.setThreshold(config.getDoingThreshold());
			serverInfo.setSleepTime(config.getSyncThreadSleepTime());
			HostInfo hostInfo = new HostInfo();
			hostInfo.setCalled(called);
			hostInfo.setTimeOut(timeOut);
			hostInfo.setDoing(ServiceServerNettyHandler.getDoing());
			hostInfo.setThreshold(config.getDoingThreshold());
			hostInfo.setSleepTime(config.getSyncThreadSleepTime());
			hostInfo.setHost(ServiceServer.getServer().getConfig().getHostUrl());
			
			if(index % config.getPutServicesCycle()==0){
				if(!ServiceStatus.getServices().getServiceDefines().isEmpty()){
					RegisterClient client = null;
					try{
						client = ServerManager.getInstance().getRegisterClient();
						client.putServices(serverInfo);
					} catch (Throwable e) {
						if(client!=null){
							LogManager.warn(SyncThread.class,"发送服务信息到注册服务器失败 Server=" + client.getHostUrl());
						}else{
							LogManager.warn(SyncThread.class,"发送服务信息到注册服务器失败,未链接到注册服务器");
						}
					}
				}
			}else if(index % config.getPutHostsCycle()==0){
				if(!ServiceStatus.getServices().getServiceDefines().isEmpty()){
					RegisterClient client = null;
					try{
						client = ServerManager.getInstance().getRegisterClient();
						client.putHosts(hostInfo);
					} catch (Throwable e) {
						if(client!=null){
							LogManager.warn(SyncThread.class,"发送微服务器信息到注册服务器失败 Server=" + client.getHostUrl());
						}else{
							LogManager.warn(SyncThread.class,"发送微服务器信息到注册服务器失败,未链接到注册服务器");
						}
					}
				}
			}
			if(config.getSyncThreadSleepTime()>0){
				timeDelay(config.getSyncThreadSleepTime());
			}
			index++;
		}
	}
	
	/**
	 * 停止服务
	 */
	public static void stop() {
		ServerManager.close();
		if(instance!=null){
			instance.stop = true;
			while(instance.thread!=null && instance.thread.isAlive()){
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
				}
			}
		}
	}

}
